﻿module BoardTool.RemoveDupFiles

open System
open System.Collections.Generic

open BoardTool.Tool
open BoardTool.Commands
open BoardTool.DirTree

let private removeDupFiles (srcRoot : string) (destRoot : string) =
    let computeFileHash (file : string) =
        use rd = new IO.StreamReader( file )
        (file, rd.ReadToEnd().GetHashCode())

    let logger = consoleLogger()

    let hashed = mapFiles "*.*" computeFileHash logger srcRoot
    
    let seeds = HashSet<string>()

    let removedCount = ref 0

    hashed.Values
    |> Seq.groupBy snd
    |> Seq.iter
        (fun (hash, entries) -> 
            let entries = 
                entries
                |> Seq.map fst
                |> Seq.toArray
            seeds.Add( entries.[0] ) |> ignore
            for i = 1 to entries.Length - 1 do
                printfn "File '%s' dropped: duplicate of '%s'" entries.[i] entries.[0]
            removedCount := !removedCount + entries.Length - 1
        )
    
    let copySeedsOnly srcFile destFile =
        if seeds.Contains( srcFile ) then
            IO.File.Copy( srcFile, destFile )

    transformFiles "*.*" copySeedsOnly logger srcRoot destRoot
    |> ignore

    printfn "Total files dropped: %d" !removedCount
    
type private RemoveDupFilesCommand( srcRoot, destRoot ) =
    interface ICommand with
        member this.id =
            sprintf "(removeDupFiles %s %s)" srcRoot destRoot

        member this.run() =
            removeDupFiles srcRoot destRoot

let REMOVE_DUP_FILES_COMMAND_FACTORY =
    { new TransformDirCommandFactory( "removeDupFiles", "removes duplicate files" ) with
        override this.createCommand( srcDir, destDir ) =
            RemoveDupFilesCommand( srcDir, destDir ) :> ICommand
    }
